﻿using System;
using System.Web;
using System.Xml;
using System.Drawing;

namespace Altairis.Nemesis.Gallery {

    public enum HorizontalAlign { Left, Center, Right }

    public enum VerticalAlign { Top, Middle, Bottom }

    internal static class ExtensionMethods {

        public static XmlElement AppendChildElementWithValue(this XmlElement e, string elementName, string innerText) {
            XmlElement childElement = e.OwnerDocument.CreateElement(elementName);
            childElement.InnerText = innerText;
            return e.AppendChild(childElement) as XmlElement;
        }

        public static bool StartsWith(this string s, params string[] values) {
            foreach (string value in values) {
                if (s.StartsWith(value, System.StringComparison.OrdinalIgnoreCase)) return true;
            }
            return false;
        }

        public static void SendCustomErrorPage(this HttpResponse r, int statusCode, string statusDescription, string message) {
            // Validate arguments
            if (statusDescription == null) throw new ArgumentNullException("statusDescription");
            if (string.IsNullOrEmpty(statusDescription)) throw new ArgumentException("Value cannot be null or empty string.", "statusDescription");

            // Create response
            r.StatusCode = statusCode;
            r.StatusDescription = statusDescription;
            r.ContentType = "text/html";
            r.Output.Write("<html><head><title>{0} {1}</title></head>", statusCode, statusDescription);
            r.Output.Write("<body><h1>{0} {1}</h1>", statusCode, statusDescription);
            if (!string.IsNullOrEmpty(message)) r.Output.Write("<p>{0}</p>", message);
            r.Output.Write("</body></html>");
            r.End();
        }

        // Image resizing

        public static Image Resize(this Image originalImage, Size newSize) {
            if (originalImage.Size == newSize) return originalImage;

            // Prepare canvas
            Size realNewSize = GetRealMaxSize(originalImage.Size, newSize);
            Bitmap targetImage = new Bitmap(realNewSize.Width, realNewSize.Height);
            Graphics gph = Graphics.FromImage(targetImage);
            gph.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
            gph.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            gph.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

            // Draw image
            gph.DrawImage(originalImage, 0, 0, realNewSize.Width, realNewSize.Height);
            return targetImage;
        }

        public static Image Resize(this Image originalImage, Size newSize, Color backgroundColor) {
            return Resize(originalImage, newSize, backgroundColor, HorizontalAlign.Center, VerticalAlign.Middle);
        }

        public static Image Resize(this Image originalImage, Size newSize, Color backgroundColor, HorizontalAlign hAlign, VerticalAlign vAlign) {
            if (originalImage.Size == newSize) return originalImage;

            // Prepare canvas
            Bitmap targetImage = new Bitmap(newSize.Width, newSize.Height);
            Graphics gph = Graphics.FromImage(targetImage);
            gph.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
            gph.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            gph.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

            // Draw background
            gph.FillRectangle(new SolidBrush(backgroundColor), 0, 0, newSize.Width, newSize.Height);

            // Set size and position of image
            Size realNewSize = GetRealMaxSize(originalImage.Size, newSize);
            Point loc = new Point(0, 0);
            switch (vAlign) {
                case VerticalAlign.Middle:
                    loc.Y = (newSize.Height - realNewSize.Height) / 2;
                    break;
                case VerticalAlign.Top:
                    loc.Y = newSize.Height - realNewSize.Height;
                    break;
                default:
                    break;
            }
            switch (hAlign) {
                case HorizontalAlign.Center:
                    loc.X = (newSize.Width - realNewSize.Width) / 2;
                    break;
                case HorizontalAlign.Right:
                    loc.X = newSize.Width - realNewSize.Width;
                    break;
                default:
                    break;
            }

            // Draw image
            gph.DrawImage(originalImage, new Rectangle(loc, realNewSize));
            return targetImage;
        }

        private static Size GetRealMaxSize(SizeF originalSize, SizeF maxSize) {
            SizeF vRatio = new SizeF(maxSize.Width / originalSize.Width, maxSize.Height / originalSize.Height);
            float ratio = vRatio.Width < vRatio.Height ? vRatio.Width : vRatio.Height;
            return new Size(System.Convert.ToInt32(originalSize.Width * ratio), System.Convert.ToInt32(originalSize.Height * ratio));
        }

    }
}
